package com.enation.app.javashop.consumer.shop.trade.consumer;

import com.enation.app.javashop.consumer.core.event.SpreadRefundCompleteEvent;
import com.enation.app.javashop.core.aftersale.AftersaleErrorCode;
import com.enation.app.javashop.core.aftersale.model.dos.RefundDO;
import com.enation.app.javashop.core.aftersale.model.enums.RefundItemStatusEnum;
import com.enation.app.javashop.core.aftersale.model.enums.RefundStatusEnum;
import com.enation.app.javashop.core.distribution.service.DistributionManager;
import com.enation.app.javashop.core.system.sendMessage.WechatSendMessage;
import com.enation.app.javashop.core.trade.order.model.dos.OrderDO;
import com.enation.app.javashop.core.trade.order.model.dos.OrderItemsDO;
import com.enation.app.javashop.core.trade.order.service.OrderQueryManager;
import com.enation.app.javashop.core.trade.sdk.model.OrderDetailDTO;
import com.enation.app.javashop.framework.database.DaoSupport;
import com.enation.app.javashop.framework.exception.ServiceException;
import com.enation.app.javashop.framework.util.BeanUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

/**
 * @author 王校长
 * @since 2020/9/10 10:29:54
 * 多退少补完成后具体操作：1.微信发送退款通知，2.修改退补状态和退补失败原因以及退款时间，
 *                          3.按照每个商品占订单总价比例扣减退补金额，4.调用【更新退款后剩余收益】方法修改各方收益
 */
@Component
public class SpreadRefundCompleteConsumer implements SpreadRefundCompleteEvent {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    @Qualifier("tradeDaoSupport")
    private DaoSupport daoSupport;

    @Autowired
    private OrderQueryManager orderQueryManager;

    @Autowired
    private DistributionManager distributionManager;

    @Autowired
    private WechatSendMessage wechatSendMessage;

    @Override
    @Transactional(value = "tradeTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void spreadRefundComplete(RefundDO refund) {

        //退款成功
        if(RefundStatusEnum.COMPLETED.value().equals(refund.getRefundStatus())){
            //1.修改退款单和退款单明细的退补状态和退款时间
            this.daoSupport.execute(
                    "update es_refund set refund_status=?, refund_time=? where sn =?",
                    refund.getRefundStatus(), refund.getRefundTime(), refund.getSn());
            this.daoSupport.execute(
                    "update es_refund_item set item_status=?, refund_time=? where refund_sn =?",
                    RefundItemStatusEnum.SUCCESS.value(), refund.getRefundTime(), refund.getSn());
            //2.调用【更新退款后剩余收益】方法修改各方收益
            OrderDetailDTO orderDetailDTO = orderQueryManager.getModel(refund.getOrderSn());
            this.updateRefundSurplusProfit(orderDetailDTO, refund.getRefundPrice());
            //3.按照每个商品占订单总价比例扣减退补金额
            this.changeOrderItemsRefundPrice(refund.getOrderSn(), refund.getRefundPrice());
            //4.微信发送退款通知
            try {
                wechatSendMessage.sendRefundMessage(refund);
            } catch (Exception e) {
                logger.error("多退少补完成后发送微信订阅消息异常:",e);
            }
        }else{
            this.daoSupport.execute(
                    "update es_refund set refund_status=?, refund_fail_reason=? where sn =?",
                    refund.getRefundStatus(), refund.getRefundReason(), refund.getSn());
            this.daoSupport.execute(
                    "update es_refund_item set item_status=?, refund_fail_reason=? where refund_sn =?",
                    RefundItemStatusEnum.FAIL.value(), refund.getRefundReason(), refund.getSn());
        }
    }

    /**
     * 按照每个商品占订单总价比例扣减退补金额
     * @param orderSn 订单号
     * @param refundPrice 退款金额
     */
    private void changeOrderItemsRefundPrice(String orderSn, Double refundPrice) {
        List<OrderItemsDO> orderItemsDOS = this.orderQueryManager.orderItems(orderSn);
        //计算订单总可退款金额
        Double totalRefundPrice = 0.0d;
        for (OrderItemsDO orderItemsDO : orderItemsDOS) {
            Double oldItemRefundPrice = orderItemsDO.getRefundPrice();
            totalRefundPrice = BigDecimal.valueOf(totalRefundPrice).add(BigDecimal.valueOf(oldItemRefundPrice))
                    .setScale(2, RoundingMode.HALF_UP)
                    .doubleValue();
        }
        for (OrderItemsDO orderItemsDO : orderItemsDOS) {
            Double oldItemRefundPrice = orderItemsDO.getRefundPrice();
            if(ObjectUtils.isEmpty(oldItemRefundPrice) || oldItemRefundPrice <= 0) {
                continue;
            }
            //orderItemPrice / totalPrice 得出占用比例
            Double itemPriceScale = BigDecimal.valueOf(oldItemRefundPrice).divide(BigDecimal.valueOf(totalRefundPrice), 6 , BigDecimal.ROUND_HALF_DOWN)
                    .doubleValue();
            //退补总金额 * itemPriceScale（比例）得出单个商品退补的金额
            Double itemRefundPrice = BigDecimal.valueOf(refundPrice).multiply(BigDecimal.valueOf(itemPriceScale))
                    .setScale(2, RoundingMode.HALF_UP)
                    .doubleValue();
            //获取单项商品可退款金额减去单项退补的金额，并限制可退款金额最小值为0
            double subtractResult = BigDecimal.valueOf(oldItemRefundPrice).subtract(BigDecimal.valueOf(itemRefundPrice))
                    .setScale(2, RoundingMode.HALF_UP)
                    .doubleValue();
            subtractResult = subtractResult < 0 ? 0.0d : subtractResult;
            //DB中将可退款金额减去单个商品退补的金额
            this.daoSupport.execute("update es_order_items set refund_price=? where item_id=?",
                    subtractResult, orderItemsDO.getItemId());
        }
    }

    /**
     * 调用更新退款后剩余收益方法从计算各方收益
     * @param orderDetailDTO 订单详情DTO
     * @param refundPrice 退款金额
     */
    private void updateRefundSurplusProfit(OrderDetailDTO orderDetailDTO, Double refundPrice) {
        OrderDO orderDO = new OrderDO();
        BeanUtil.copyProperties(orderDetailDTO, orderDO);
        //获取订单可退款金额
        double orderRefundPrice = orderQueryManager.getOrderRefundPrice(orderDetailDTO.getSn());
        double newOrderPrice = BigDecimal.valueOf(orderRefundPrice).subtract(BigDecimal.valueOf(refundPrice))
                .setScale(2, RoundingMode.HALF_UP)
                .doubleValue();
        if (orderRefundPrice <= 0 || newOrderPrice < 0){
            throw new ServiceException(AftersaleErrorCode.E600.name(), "订单号：[" + orderDO.getSn() + "]" + AftersaleErrorCode.E600.describe());
        }
        distributionManager.updateRefundSurplusProfit(orderDO, orderRefundPrice, newOrderPrice);
    }
}
